package com.bonzaster;

import android.content.Context;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Environment;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * Created by IntelliJ IDEA.
 * User: Damir
 * Date: 18.04.2010
 * Time: 23:29:36
 */
public class MainThread implements Runnable
{
    public interface PhotoShootListener
    {
        void onPhotoShooted(String info);
    }

    public boolean isCameraReady = false;
    public boolean isThreadStopping = true;

    private static final String TAG = "!!!PhotoSeries";
    public Camera mCamera;
    private Camera.Parameters mCameraParameters;
    public Thread workThread;
    private int mDelaySeconds;
    private int mDelayMinutes;

    SurfaceView mPreview;
    SurfaceHolder mPreviewHolder;

    private PhotoShootListener mShootListener;
    private final SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyyMMdd-HHmmssSSS");
    private String mNowDateTime = "";
    private String mDir;
    private String mFile;
    private File mRootDir;
    private SoundPool mSoundPool;
    private int soundId;
    private Object sync = new Object();
    private File mSDCardRoot;

    public MainThread(SurfaceView sv, Context c, PhotoShootListener l)
    {
        mShootListener = l;
        mSDCardRoot = Environment.getExternalStorageDirectory();
        if (!mSDCardRoot.canWrite())
        {
            notifyListener("Error: can't write to SD card");
            return;
        }
        mSoundPool = new SoundPool(4, AudioManager.STREAM_MUSIC, 100);
        soundId = mSoundPool.load(c, R.raw.ding, 1);
        mPreview = sv;
        mPreviewHolder = mPreview.getHolder();
        mPreviewHolder.addCallback(previewHolderCallback);
        mPreviewHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
    }

    public void applyPreferences(int delayMinutes, int delaySeconds, String dirName, String fileName)
    {
        mDelayMinutes = delayMinutes;
        mDelaySeconds = delaySeconds;
        mDir = dirName;
        mFile = fileName;
        mRootDir = new File(mSDCardRoot, mDir);
    }

    public void run()
    {
        if (!mRootDir.exists())
        {
            if (!mRootDir.mkdir())
            {
                notifyListener("Error: could not create destination directory");
                isThreadStopping = true;
                return;
            }
        }
        while (!isThreadStopping)
        {
            try
            {
                synchronized (sync)
                {
                    Log.e(TAG, "taking picture");
                    mCamera.takePicture(shutterCallback, null, pictureTakenCallback);
                    sync.wait(mDelayMinutes * 60000 + mDelaySeconds * 1000);
                }
            }
            catch (Exception e)
            {
                notifyListener(e.getMessage());
                e.printStackTrace();
            }
        }
    }

    private Camera.PictureCallback pictureTakenCallback = new Camera.PictureCallback()
    {
        public void onPictureTaken(byte[] bytes, Camera camera)
        {
            synchronized (sync)
            {
                mNowDateTime = mDateFormat.format(new Date());
                try
                {
                    FileOutputStream fos = new FileOutputStream(new File(mRootDir, mFile + mNowDateTime + ".jpg").getPath());
                    fos.write(bytes);
                    fos.close();
                    notifyListener("file " + mFile + mNowDateTime + ".jpg saved");
                    mCamera.startPreview();
                } catch (IOException e)
                {
                    notifyListener(e.getMessage());
                    e.printStackTrace();
                }
            }
        }
    };

    private Camera.ShutterCallback shutterCallback = new Camera.ShutterCallback()
    {
        public void onShutter()
        {
            //mSoundPool.play(soundId, 100, 100, 1, 0, 1);
        }
    };

    public void start()
    {
        synchronized (sync)
        {
            isThreadStopping = false;
            workThread = new Thread(this);
            workThread.start();
        }
    }

    public void stop()
    {
        synchronized (sync)
        {
            isThreadStopping = true;
            sync.notify();
        }
    }

    private void notifyListener(String info)
    {
        if (mShootListener != null)
            mShootListener.onPhotoShooted(info);
        else
            Log.e(TAG, "listener is null");
    }

    SurfaceHolder.Callback previewHolderCallback = new SurfaceHolder.Callback()
    {
        public void surfaceCreated(SurfaceHolder surfaceHolder)
        {
            Log.e(TAG, "surfaceCreated");
            try
            {
                mCamera = Camera.open();
                try
                {
                    mCamera.setPreviewDisplay(surfaceHolder);
                    isCameraReady = true;
                    notifyListener("ready to shoot");
                }
                catch (IOException e)
                {
                    mCamera.release();
                    mCamera = null;
                    throw e;
                }
            } catch (Exception e)
            {
                notifyListener(e.getMessage());
                e.printStackTrace();
            }
        }

        public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int width, int height)
        {
            Log.e(TAG, "surfaceChanged");
            if (isCameraReady)
            {
                mCameraParameters = mCamera.getParameters();
                mCameraParameters.setPictureFormat(PixelFormat.JPEG);
                mCameraParameters.setPreviewSize(width, height);
                mCameraParameters.set("focusMode", "infinity");
                mCamera.setParameters(mCameraParameters);
                mCamera.startPreview();
            }
        }

        public void surfaceDestroyed(SurfaceHolder surfaceHolder)
        {
            Log.e(TAG, "surfaceDestroyed");
            isCameraReady = false;
            if (mCamera != null)
            {
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            }
        }
    };

}